using System;
using System.Collections.Generic;
using System.Text;
using interfaces;

namespace retrofit
{
    public class Output
    {
        // energy unit conversion factor for electricity and gas
        public static double[] m_conversion = new double[] { 3.6E+9, 1E+9 };

		public double[] m_energy;				/// energy output array for each energy type
        public double[] m_energyTotal;			/// energy output array for total electricity and gas energy

		public double[] m_energyCost;			/// energy cost for each energy category
		public double[] m_energyTotalCost;		/// total energy cost

		public double m_energySumTotalCost;		/// total summamation energy cost (gas + electricity)


        /// <summary>
        ///  constructor of Output class to initialize output array.
        /// </summary>
        public Output()
        {
            m_energy = new double[(int)Keyword.energy_cat_t.NUM_ECT];
            m_energyTotal = new double[(int)Keyword.energy_form_t.NUM_EFT];

			m_energyCost = new double[(int)Keyword.energy_cat_t.NUM_ECT];
			m_energyTotalCost = new double[(int)Keyword.energy_form_t.NUM_EFT];
        }


		/// <summary>
		/// calculate energy cost based on iput rate
		/// </summary>
		/// <param name="rate">energy rate array, accessed through Keyword.energy_form_t</param>
		public void calcEnergyCost(double[] rate)
		{
			// calculate energy total and cost
			for (int i = 0; i < m_energyCost.Length; ++i)
			{
				Keyword.energy_form_t form = Keyword.m_energy_form[i];
				m_energyCost[i] = m_energy[i] * rate[(int)form];
				//Console.WriteLine(m_energyCost[i] + ", ");
			}

			//Console.WriteLine("!");
		}


        /// <summary>
        ///  Loop over the energy output array to get total electricity and gas energy.
        /// </summary>
        public void calcTotalEnergy()
        {
			// calculate energy total and cost
            for (int i = 0; i < m_energy.Length; ++i)
            {
                Keyword.energy_form_t form = Keyword.m_energy_form[i];
                m_energyTotal[(int)form] += m_energy[i];
				m_energyTotalCost[(int)form] += m_energyCost[i];
				//Console.WriteLine(m_energyTotalCost[(int)form] + ", ");
            }

			//Console.WriteLine("#");

			// calculate energy sum total cost
            for (int i = 0; i < m_energyTotalCost.Length; ++i)
			{
				m_energySumTotalCost += m_energyTotalCost[i];
			}
        }


        /// <summary>
		/// Calculate energy difference between retrofit output energy and original output energy.
		/// diff = retro - orig
        /// </summary>
        /// </summary>
		/// <param name="retro">the original energy output</param>
		/// <param name="orig">the retrofit energy output</param>
		public void diff(Output retro, Output orig)
        {
            // calculate energy difference for each output energy type
            for (int i = 0; i < (int)Keyword.energy_cat_t.NUM_ECT; ++i )
            {
				m_energy[i] = retro.m_energy[i] - orig.m_energy[i];
				m_energyCost[i] = retro.m_energyCost[i] - orig.m_energyCost[i];
            }

            // calculate total energy difference
            for (int i = 0; i < (int)Keyword.energy_form_t.NUM_EFT; ++i)
            {
				m_energyTotal[i] = retro.m_energyTotal[i] - orig.m_energyTotal[i];
				m_energyTotalCost[i] = retro.m_energyTotalCost[i] - orig.m_energyTotalCost[i];
            }

			m_energySumTotalCost = retro.m_energySumTotalCost - orig.m_energySumTotalCost;
        }

        
		/// <summary>
		/// this is operator "-" (substration) overloading fucntion to implement retro - orig
        /// this function is the same with diff(out1, out2) function.
        /// </summary>
		/// <param name="retro">the original energy output</param>
		/// <param name="orig">the retrofit energy output</param>
        /// <returns>the result of deduction</returns>
		public static Output operator -(Output retro, Output orig)
        {
            Output diff = new Output();

            // calculate energy difference for each output energy type
            for (int i = 0; i < (int)Keyword.energy_cat_t.NUM_ECT; ++i)
            {
				diff.m_energy[i] = retro.m_energy[i] - orig.m_energy[i];
				diff.m_energyCost[i] = retro.m_energyCost[i] - orig.m_energyCost[i];

            }

            // calculate total energy difference
            for (int i = 0; i < (int)Keyword.energy_form_t.NUM_EFT; ++i)
            {
				diff.m_energyTotal[i] = retro.m_energyTotal[i] - orig.m_energyTotal[i];
				diff.m_energyTotalCost[i] = retro.m_energyTotalCost[i] - orig.m_energyTotalCost[i];
            }

			// calculate sum total energy cost
			diff.m_energySumTotalCost = retro.m_energySumTotalCost - orig.m_energySumTotalCost;

			return diff;
        }


		/// <summary>
		/// this is operator "/" (division) overloading fucntion to implement difference / original
		/// </summary>
		/// <param name="diff">the energy output difference</param>
		/// <param name="orig">the original energy output</param>
		/// <returns>the ratio of retrofit difference to original case</returns>
		public static Output operator /(Output diff, Output orig)
		{
			Output ratio = new Output();

			// calculate energy difference for each output energy type
			for (int i = 0; i < (int)Keyword.energy_cat_t.NUM_ECT; ++i)
			{
				if (orig.m_energy[i] <= 0)
					ratio.m_energy[i] = 0;
				else
					ratio.m_energy[i] = diff.m_energy[i] / orig.m_energy[i];

				if (orig.m_energyCost[i] <= 0)
					ratio.m_energyCost[i] = 0;
				else
					ratio.m_energyCost[i] = diff.m_energyCost[i] / orig.m_energyCost[i];
			}

			// calculate total energy difference
			for (int i = 0; i < (int)Keyword.energy_form_t.NUM_EFT; ++i)
			{
				ratio.m_energyTotal[i] = diff.m_energyTotal[i] / orig.m_energyTotal[i];
				ratio.m_energyTotalCost[i] = diff.m_energyTotalCost[i] / orig.m_energyTotalCost[i];
			}

			// calculate sum total energy cost
			ratio.m_energySumTotalCost = diff.m_energySumTotalCost / orig.m_energySumTotalCost;

			return ratio;
		}


		/// <summary>
		/// Calculate life cycle energy savings.
		/// </summary>
		/// <param name="diff">the difference energy Output variable</param>
		/// <param name="economic">the economic input information, access by using enum Building.BEE_BuildingEconomic_T</param>
		public static Output calcLifeCycleOutput(Output diff, double[] economic)
		{
			Output eco = new Output();

			// calculate each energy category use and cost
			for (int i = 0; i < (int)Keyword.energy_cat_t.NUM_ECT; ++i)
			{
				eco.m_energy[i] = diff.m_energy[i] * economic[(int)Building.BEE_BuildingEconomic_T.EvaluationPeriod_BET];
				eco.m_energyCost[i] = diff.m_energyCost[i] * economic[(int)Building.BEE_BuildingEconomic_T.EvaluationPeriod_BET];
			}

			return eco;
		}


        /// <summary>
        /// unit conversion fution to convert electricity to [MWH] and gas to [GJ].
        /// </summary>
        public void unitConversion()
        {
            for (int i = 0; i < (int)Keyword.energy_cat_t.NUM_ECT; ++i)
            {
                int type = (int)Keyword.m_energy_form[i];
                m_energy[i] = m_energy[i] / m_conversion[type];
            }
        }
    }
}
